package com.lin.fengxiu.logic;

import com.lin.fengxiu.bo.SkuOrderBO;
import com.lin.fengxiu.dto.OrderDTO;
import com.lin.fengxiu.dto.SkuInfoDTO;
import com.lin.fengxiu.exception.http.ParameterException;
import com.lin.fengxiu.model.OrderSku;
import com.lin.fengxiu.model.Sku;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName OrderChecker
 * @Description TODO 订单校验
 * @Author wushaopei
 * @Date 2021/4/4 10:21
 * @Version 1.0
 */
public class OrderChecker {

    private OrderDTO orderDTO;
    private List<Sku> serverSkuList;
    private CouponChecker couponChecker;
    private Integer maxSkuLimit;
    // orderSkuList
    @Getter
    private List<OrderSku> orderSkuList = new ArrayList<>();

    /**
     * @Description TODO 订单校验主体
     * @param orderDTO  订单主体信息
     * @param serverSkuList  订单的skuList
     * @param couponChecker  订单所使用的优惠券校验
     */
    public OrderChecker(OrderDTO orderDTO, List<Sku> serverSkuList, CouponChecker couponChecker
                        ,Integer maxSkuLimit){
        this.orderDTO = orderDTO;
        this.serverSkuList = serverSkuList;
        this.couponChecker = couponChecker;
        this.maxSkuLimit = maxSkuLimit;
    }

    /**
     * @Description TODO 获取订单的主要图片
     * @return
     */
    public String getLeaderImg(){
        return this.serverSkuList.get(0).getImg();
    }
    /**
     * @Description TODO 获取订单的主要title
     * @return
     */
    public String getLeaderTitle(){
        return this.serverSkuList.get(0).getTitle();
    }

    /**
     * @Description TODO 订单购买总量，直接累加所有的sku的count就行
     * @return
     */
    public Integer getTotalCount(){
        return this.orderDTO.getSkuInfoList()
                .stream()
                .map(SkuInfoDTO::getCount)
                .reduce(Integer::sum)
                .orElse(0);
    }
    /**
     * @Description TODO 订单是否有效
     */
    public void isOK(){

        BigDecimal serverTotalPrice = new BigDecimal("0");
        List<SkuOrderBO> skuOrderBOList = new ArrayList<>();

        // 校验前后端订单sku是否一致
        this.skuNotOnSale(orderDTO.getSkuInfoList().size(), this.serverSkuList.size());
        // 循环查询前后端sku
        for(int i = 0 ; i < this.serverSkuList.size(); i++){
            // 根据后端的serverSkuList查询对应sku，由于后端的skuList是根据前端的循环获取的，所以两者长度、序号一致的sku也一致
            Sku sku = this.serverSkuList.get(i);
            SkuInfoDTO skuInfoDTO = this.orderDTO.getSkuInfoList().get(i);
            // 校验当前sku是否售罄
            this.containsSoldOutSku(sku);
            // 是否库存超卖
            this.beyondSkuStock(sku,skuInfoDTO);
            // 是否sku最大购买量超卖
            this.beyondMaxSkuLimit(skuInfoDTO);
            // 计算当前sku所购买数量的总额，例：外套5件 * 100 = 500
            serverTotalPrice = serverTotalPrice.add(this.calculateSkuOrderPrice(sku, skuInfoDTO));
            // 返回有效的skuOrderBOList
            skuOrderBOList.add(new SkuOrderBO(sku,skuInfoDTO));
            // 组装 orderSkuList
            this.orderSkuList.add(new OrderSku(sku, skuInfoDTO));
        }
        // 校验前后端总原价是否一致
        this.totaoPriceIsOk(orderDTO.getTotalPrice(),serverTotalPrice);

        // 调用 CouponChecker 校验
        if(this.couponChecker != null){
            this.couponChecker.isOk();
            this.couponChecker.canBeUsed(skuOrderBOList, serverTotalPrice);
            this.couponChecker.finalTotalPriceIsOk(orderDTO.getFinalTotalPrice(),serverTotalPrice);
        }
    }

    /**
     * @Description TODO 计算前端传过来的总原价和后端计算的总原价是否一致
     * @param orderTotalPrice
     * @param serverTotalPrice
     */
    private void totaoPriceIsOk(BigDecimal orderTotalPrice, BigDecimal serverTotalPrice){
        if(orderTotalPrice.compareTo(serverTotalPrice)!=0){
            throw new ParameterException(50005);
        }
    }

    /**
     * @Description TODO 根据前端传过来的sku数量，通过和Sku相乘获取当前SKU所购买数量的总额
     * @param sku
     * @param skuInfoDTO
     * @return
     */
    private BigDecimal calculateSkuOrderPrice(Sku sku, SkuInfoDTO skuInfoDTO){
        if(skuInfoDTO.getCount() <= 0){
            throw new ParameterException(50007);
        }
        return sku.getActualPrice().multiply(new BigDecimal(skuInfoDTO.getCount()));
    }

    /**
     * @Description TODO 当前sku库存是否超卖 -- 购买数量是否超过sku的库存量
     * @param sku
     * @param skuInfoDTO
     */
    private void beyondSkuStock(Sku sku, SkuInfoDTO skuInfoDTO) {
        if(sku.getStock() < skuInfoDTO.getCount()){
            throw new ParameterException(50003);
        }
    }

    /**
     * @Description TODO 当前sku是否超过限定的购买量
     * @param skuInfoDTO
     */
    private void beyondMaxSkuLimit(SkuInfoDTO skuInfoDTO){
        if(skuInfoDTO.getCount() > this.maxSkuLimit){
            throw new ParameterException(50004);
        }
    }

    /**
      * @Description TODO 校验当前sku是否售罄
      * @param sku
     */
    private void containsSoldOutSku(Sku sku) {
        if(sku.getStock() == 0){
            throw new ParameterException(50001);
        }
    }

    /**
     * @Description TODO 校验sku数量是否一致
     * @param size
     * @param size1
     */
    private void skuNotOnSale(int size, int size1) {
        if(size != size){
            throw new ParameterException(50002);
        }
    }
}
